<?php
namespace app\common\model;
use think\Model;
use think\Db;
use app\common\model\Redis;
use app\common\model\Dev_data_info;
use app\common\model\Wechat;
class Dev_info extends Model
{

	/**
	 * 获取单条设备信息
	 * @param  [array] $where [数组]
	 * @return [type]        [description]
	 */
	public function getOne($where,$field='*'){
        $result = self::field($field)->where($where)->find();
        if($result){
            $result = $result->getData();
        }
        return $result;
	}

    /**
     * 获取列表
     * @param int $end 结束时间
     * @return array
     * */
    public function getAll($where=[],$field="*",$type=false){
        $result = self::field($field);
        
        if ($where){
            $result->where($where);
        }
        $result = $result->select();

        if($type){
            if($result){
                $result = endoceArr($result);
            }
        }

        return $result;
    }

    /**
     * 获取单条设备信息
     * @param  [array] $where [数组]
     * @return [type]        [description]
     */
    public function getDevAll($where=[],$order,$field='*',$pageSize=15,$pageParam=[]){

        $result = self::field($field)->order($order);
        if($where){
            $result = $result->where($where);
        }
        $result = $result->paginate($pageSize,false,$pageParam);
        return $result;
    }


	/**
     * 更改
     * @param $id
     * @param $data
     * @return $this
     */
    public function updInfo($where,$data){
        return self::where($where)->update($data);
    }

    /**
     * 将设备  积累型参数|可控参数|操作单位  存在redis
     * @param  [string] $dev_id [description]
     */
    public function accumulateRedis($dev_id){

        $redis = new Redis();
        $redis->select(1);
        $redis->del($dev_id."_his_para");
        $redis->del($dev_id."_owner_para");


        $field = "d.d_id,d.unit_id,d.if_his,d.view,u.val";
        $dinfo = self::alias('d')->join("unit_table AS u ON (d.unit_id=u.unit_id)","left")->field($field)->where(["d.guid1"=>$dev_id])->select();

        if($dinfo){
            $dinfo = endoceArr($dinfo);
            foreach ($dinfo as $key => $value) {
                //存操作单位
                $redis->hset($dev_id."_para_info",$value["d_id"],$value["val"]);

                //存积累型参数
                if($value["if_his"]){
                    $redis->lpush($dev_id."_his_para",$value["d_id"]);
                }

                //存可控参数
                if($value["view"]){
                    $redis->lpush($dev_id."_owner_para",$value["d_id"]);
                }
            }
        }
    }

    /**
     * 将设备当天数据存在 redis
     * @param [string] $dev_id [设备id号]
     * @param [string] $tz [设备时区]
     */
    public function dataRedis($dev_id,$tz){

        $setime = get_today_start_and_end_timestamp_on_the_timezone($tz);

        //查出当天数据,且存入redis
        $table = get_his_data_table($dev_id);
        $where["guid1"] = $dev_id;
        $where["t"] = array('between',array($setime['st'],$setime['et']));;
        $info = db($table)->where($where)->field("d_id,val,t")->select();
        if($info){
            $redis = new Redis();
            $redis->select(1);
            $info = endoceArr($info);
            foreach($info as $_v){
                $redis->zadd($dev_id."_".$_v["d_id"]."_data",$_v["t"],$_v["val"]);
            }
        }
    }

    /**
     * 获取设备当天数据
     * @param  [type] $guid1 [设备号]
     * @param  [type] $view  [0：企业，1：开发者]
     * @param  [type] $t     [web当前拥有的最新数据时间戳(秒为单位).0表示web端目前没有任何该设备数据]
     * @return [type]        [description]
     */
    public function getDayData($guid1,$view,$t){

        $this->redis = new Redis();
        $data = array();
        $select = $this->redis->whereRedis($guid1);
        if(is_bool($select)){
            return $data;
        }else{
            $this->redis->select($select);
        }

        //获取该设备当地时区当天开始时间
        $tz = $this->redis->hget($guid1,"tz");
        $setime = get_today_start_and_end_timestamp_on_the_timezone($tz);
        $this->redis->select(1);
        $resll_id = $this->redis->lranges($guid1."_owner_para");
        $info = $this->redis->hGetAll($guid1."_para_info");
        $j = 0;

        foreach ($info as $key => $value) {
            
            $devid = $guid1."_".$key."_data";

            if($view==1){
                if(!in_array($key,$resll_id)){
                    continue;
                }
            }elseif($view==0){
                if(in_array($key,$resll_id)){
                    continue;
                }
            }

            if($t==0){
                // redis 中查， >= $setime["st"]
                $res = $this->redis->zRangeByScore($devid,$setime["st"],"+inf",TRUE);
            }else {
                // >$setime["st"]
                $res = $this->redis->zRangeByScore($devid,$t,time(),TRUE);
        
            }
            if($res){
                //操作id
                $data[$j]["did"] = $key;
                //单位
                $unit = $value;
        
                switch ($unit) {
                    case 'sys/bin':
                    case 'sys/state-bin':
                        $i = 0;
                        foreach($res as $_k=>$_v){
                           $arr = explode("_", $_k);
                           $data[$j]["v"][$i] = $arr[0];
                           $data[$j]["t"][$i] = $_v;
                           $i++;
                        }
                        break;
                    case 'sys/file':
                    case 'sys/file-video':
                    case 'sys/file-audio':
                    case 'sys/file-image':
                        $i = 0;
                        foreach($res as $_k=>$_v){
            
                           $data[$j]["v"][$i] = $_k;
                           $data[$j]["t"][$i] = $_v;
                           $i++;
                        }

                        break;
                    case 'sys/file-pcloud':
                        $i = 0;
                        foreach($res as $_k=>$_v){
                           if(file_exists($_k)){
                               //读取二进制文件时，需要将第二个参数设置成'rb'
                               $handle = fopen($_k, "r");
                               //通过filesize获得文件大小，将整个文件一下子读到一个字符串中
                               $contents = fread($handle, filesize ($_k));
                               fclose($handle);
                               $data[$j]["v"][$i] = $contents;
                           }else{
                               $data[$j]["v"][$i] = $contents;
                           }
                           $data[$j]["t"][$i] = $_v;
                           $i++;
                        }
                        break;
                    case 'sys/file-stl':
                        $i = 0;
                        foreach($res as $_k=>$_v){
                           if(file_exists($_k)){
                               $data[$j]["v"][$i] = $_k;
                           }else{
                               $data[$j]["v"][$i] = "";
                           }
                           $data[$j]["t"][$i] = $_v;
                           $i++;
                        }
                        break;
                    case strstr($unit,'sys/file-hz-')==true:
                        $i = 0;
                        foreach($res as $_k=>$_v){
                           if(file_exists($_k)){
                               $handle = fopen($_k, "r");
                               //通过filesize获得文件大小，将整个文件一下子读到一个字符串中
                               $contents = fread($handle, filesize ($_k));
                               fclose($handle);
                               $data[$j]["v"][$i] = $contents;
                           }else{
                               $data[$j]["v"][$i] = $contents;
                           }
                           $data[$j]["t"][$i] = $_v;
                           $i++;
                        }
                        break;
                    default:
                        $i = 0;
                        foreach($res as $_k=>$_v){
                           $arr = explode("_", $_k);
                           $data[$j]["v"][$i] = $arr[0];
                           $data[$j]["t"][$i] = $_v;
                           $i++;
                        }
                        break;
                }
            }else{
                //如redis中没有，则以1%的概率从mysql中查找,并将该设备信息导入到redis中
                if(chance(1)){
                    $where = array();
                    $where["guid1"] = $guid1;
                    $where["d_id"] = $key;
                    $where['t']  = array('between',array($setime["st"],$setime["et"]));
                    $table = get_his_data_table($guid1);
                    $rlist = M($table)->where($where)->select();

                    $rlist = endoceArr($rlist);

                    $data[$j]["did"] = $key;
                    foreach ($rlist as $k => $v) {
                        $data[$j]["v"][$k] = $v["val"];
                        $data[$j]["t"][$k] = $v["t"];
                        $this->redis->zadd($devid,$v["t"], $v["val"]."_".strval($v["t"]%1000000));
                    }
                }
                continue;
            }

            $j++;
        }

        return $data;
    }

    /**
     * 将当天数据存入mysql
     */
    public function dayDataMysql($devid,$select=""){
        $redis = new Redis();
        if(!$select){
            //主要为了时区
            $select = $this->whereRedis($devid);
            if(is_bool($select)){
                //redis中不存在就查数据库
                $sq = $this->getOne(["guid1"=>$devid],'tz');
                $tz = $sq["tz"];
            }else{
                $redis->select($select);
                $tz = $redis->hget($devid,"tz");
            }
        }
        //查出设备所在时区,然后算去当天的开始于结束时间
        $setime = get_today_start_and_end_timestamp_on_the_timezone($tz);
        $redis->select(1);

        //查出此设备的积累型did
        $id = $redis->lranges($devid."_his_para");

        //查出此设备 可控id
        $resll_id = $redis->lranges($devid."_owner_para");
        $table = get_his_data_table($devid);
        foreach($id as $_k=>$_v){
            $dev_id = $devid."_".$_v."_data";
            //判断是否有当天数据,有则存入mysql
            $res = $redis->zRangeByScore($dev_id,$setime['st'],$setime['et'],TRUE);
            if($res){
                //可控id
                $view = in_array($_v,$resll_id)?1:0;
                //单位
                $unit = $redis->hget($devid."_para_info",$_v);

                //查出数据库中已存在的最后一条数据的时间
                $last1 = M($table)->where(array("guid1"=>$devid,"d_id"=>$_v))->field("t")->order("t desc")->limit(1)->find();

                if($last1){
                    $last1 = $last1->getData();
                }

                $mysqli = new \mysqli(config('database.hostname'),config('database.username'),config('database.password'),config('database.database'));
                foreach($res as $k=>$r){
                    if($last1){
                        //当前时间小于 mysql最新时间,代表着此数据已经存在了mysql,则跳出此循环
                        if($r<$last1["t"]){
                            continue;
                        }
                    }
                    $val = explode("_", $k);
                    $val = $val[0];
                    $sql = "INSERT INTO $table (`guid1`,`d_id`,`unit`,`val`,`t`,`view`) VALUES('{$devid}','{$_v}','{$unit}',$val,$r,'{$view}')";
                    $mysqli->query($sql);
                }

            }
        }
    }

    /**
     * 从redis中随机选取设备,根据其最后数据更新时间，判断是否超过4小时未活动,是,将其从redis中(包含积累与非积累型数据)存入mysql,将其信息从redis中删除
     * @param  [string] $guid1  [设备号]
     * @param  [string] $select [所在数据库]
     */
    public function redis_cleaner($guid1,$select){
        //获取最后更新时间
        $redis = new Redis();
        $redis->select($select);
        $time = 60*60*4;
        $end_time = $redis->hget($guid1,"last_upload");

        if(time()-$end_time>$time){
            
            //积累型
            $redis->select(1);
            $info = $redis->hGetAll($guid1."_para_info");
            $did = $redis->lranges($guid1."_his_para");
            $resll_id = $redis->lranges($guid1."_owner_para");
            foreach($info as $_k=>$_v){
                //积累性参数
                $devid = $guid1."_".$_k."_data";
                if(in_array($_k,$did)){
                    $res = $redis->zRange($devid,0,-1,TRUE);
                    if($res){
                        $view = in_array($_k,$resll_id)?1:0;

                        //将非当天数据存入mysql,先获取表名,再存入数据库,再删除redis
                        $table = get_his_data_table($guid1);
                        $mysqli = new \mysqli(config('database.hostname'),config('database.username'),config('database.password'),config('database.database'));
                        foreach($res as $k=>$r){
                            $res = explode("_", $k);
                            $sql = "INSERT INTO $table (`guid1`,`d_id`,`unit`,`val`,`t`,`view`) VALUES('{$guid1}','{$_k}','{$_v}',$res[0],$r,'{$view}')";
                            $mysqli->query($sql);
                        }
                    }
                }
                $redis->del($devid);
            }
            $redis->del($guid1."_para_info");
            $redis->del($guid1."_his_para");
            $redis->del($guid1."_owner_para");

            $redis->select($select);
            $redis->del($guid1);
        }
    }

    /**
     * 查看设备信息
     * @param [string] guid1 [设备号]
     * @param [string] field [字段 可为NULL]
     */
    public function is_exist($guid1,$field=NULL){
        
        $res = FALSE;
        if($guid1){
            
            $res = self::where(["guid1"=>$guid1]);
            if($field){
                $res = $res->field($field);
            }
            $res = $res->find();

            if($res){
                $res = $res->getData();
            }
        }

        return $res;
    }

    /**
     * 生成设备微信二维码
     * @param  [string] $dev_id [设备号]
     * @return [array]         [code:true false  msg:图片路径]
     */
    public function createCode($dev_id,$path=""){
        //查看是否已经存在
        if(!$path){
            $path = config("WETCHAT_CODE");
        }
        
        $filename = $path.$dev_id.".jpg";
        if(file_exists($filename)){
            $data = array(
                 "code"=>true,
                 "msg"=>$filename
            );
        }else{
            $weixin = new Wechat();
            $return = $weixin->createCode($dev_id);
            if($return["code"]){
                $data = array(
                     "code"=>true,
                     "msg"=>$return['msg']
                );
            }else{
                $data = array(
                     "code"=>false,
                     "msg"=>"生成失败"
                );
            }
        }

        return $data;
    }

    /**
     * 警报发送
     * @param  [string]  $devid [设备号]
     * @param  [string]  $type  [ 1:警报异常 2:解除警报]
     * @return [type]         [description]
     */
    public function sendA($devid, $type){
        $cmd = 'php /var/www/html/ferr/public/run/alarm.php '.$devid.' '.$type.' &>/tmp/php.log';
        pclose(popen($cmd, 'r'));
    }

}